//! \file Gui.cpp
//! \brief TODO: Document
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------

#include "Gui.h"
#include "GuiSDL.h"
#include "GuiOpenGL.h"
#include "GuiCEGUI.h"
#include "Elements.h"
#include "Core.h"
#include <unistd.h> // TODO: remove after removing sleep();

// =====[ Local Definitions ]===================================================

// =====[ Local DataTypes ]=====================================================

// =====[ Local Variables ]=====================================================
GUI* GUI::m_pGui = NULL;        //!< The singleton object instance.
bool GUI::m_IsRunning = false;  //!< TODO: comment

// =====[ Local Functions ]=====================================================

// =====[ Private (Internal) Methods ]==========================================

// =====[ Local Implementation ]================================================


// =============================================================================
// GUI::getSingleton
// -----------------------------------------------------------------------------
//! Returns a reference to the instanced singleton object.
//!
//! \retval Singleton
//!   A reference to the instanced singleton object.
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
GUI& GUI::getSingleton()
{
  // Only allow one instance of class to be generated.
  if (!m_pGui) { m_pGui = new GUI; }  // Create our single instance.
  return (*m_pGui);                   // Finally, return our singleton.
}


// =============================================================================
// GUI::getSingletonPtr
// -----------------------------------------------------------------------------
//! Returns a pointer to the instanced singleton object.
//!
//! \retval Singleton
//!   A pointer to the instanced singleton object.
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
GUI* GUI::getSingletonPtr()
{
  // Only allow one instance of class to be generated.
  if (!m_pGui) { m_pGui = new GUI; }  // Create our single instance.
  return (m_pGui);                    // Finally, return our singleton.
}


// =============================================================================
// GUI::start
// -----------------------------------------------------------------------------
//! Starts the graphical user interface (GUI) component.  TODO: more details.
//!
//! \retval Error
//!   The success status of the requested operation.
//!   - ERR_NONE: Execution occurred as requested.
//!   - Otherwise: An error code identifying the specific error.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
tERROR GUI::start(void)
{
  const Core::tTask Task = { &run, &stop };
  tERROR Error;

  // Create and start the new task running.
  m_IsRunning = true;           // Flag that we're running.
  Error = Core::TaskNew(&Task); // Create and start the new task.

  // There was an error starting the task, flag it as such.
  if (Error != ERR_NONE) { m_IsRunning = false; }

  // Finally, return the error status.
  return (Error);
}


// =============================================================================
// GUI::stop
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
tERROR GUI::stop(tERROR Error)
{
  m_IsRunning = false; // TODO: see shutdown
  return (ERR_NONE); // Return success.
}


// =============================================================================
// GUI::run
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
void *GUI::run(void *Arg)
{
  tERROR Error;

  // Initialize the GUI.
  if ((Error = initialize()) != ERR_NONE)
    { Core::TaskRequestShutdown(Error); }

  // TODO: comment
  while (m_IsRunning == true)
  {
    // TODO: comment
    GuiCEGUI::getSingleton().inject();

    // Render the GUI.
    render();


//    inject_input(must_quit);
//    inject_time_pulse(last_time_pulse);
//    render_gui();

//    Core::LogMessage("GUI::run");
//    sleep(1);
  }

  // Complete the task.
  return (Core::TaskComplete(NULL));
}


// =============================================================================
// GUI::initialize
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
tERROR GUI::initialize(void)
{
  GuiSDL::getSingleton().start();     // Start the SDL layer.
  GuiOpenGL::getSingleton().start();  // Start the OpenGL layer.
  GuiCEGUI::getSingleton().start();   // Start the CEGUI layer.
  createElements();                   // Create all the GUI elements.
  return (ERR_NONE);                  // Return success.
}


// =============================================================================
// FxName
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
void GUI::createElements(void)
{
  // TODO: create the elements.
  MenuMain::create();
  WindowConsole::create();
  WindowDice::create();

  // load some demo windows and attach to the background 'root'
  //Window* background = GuiCEGUI::getWm()->createWindow("Vanilla/StaticImage");
  //Window* background = GuiCEGUI::getWm()->createWindow("TaharezLook/StaticImage");
  //GuiCEGUI::getRoot()->addChildWindow(GuiCEGUI::getWm()->loadWindowLayout("dungeonquest.layout"));

  // Return success.
}


// =============================================================================
// GUI::render
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
void GUI::render(void)
{
  // Clear the buffer.
  GuiOpenGL::getSingleton().clear();

  // TODO: draw our stuff???
//  Gui::DisplayTask(NULL);

  // Render CEGUI.
  GuiCEGUI::getSingleton().render();

  // Update the screen with a page flip.
  GuiSDL::swapBuffers();
}

